/*
 * Copyright (c) 2020 HiHope Community.
 * Description: IoT Platform
 * Author: HiSpark Product Team
 * Create: 2020-5-20
 */

#include "iot_config.h"
#include "iot_log.h"
#include "iot_main.h"
#include "iot_profile.h"
#include <hi_task.h>
#include <string.h>
#include <app_demo_traffic_sample.h>


extern hi_u8 g_current_mode;
extern hi_u8 g_current_type;
extern hi_u8 g_someone_walking_flag;
extern hi_u8 g_with_light_flag;
extern hi_u8 g_menu_select;
extern hi_float g_temperature;
extern hi_float g_humidity;
extern hi_float g_combustible_gas_value ;
extern hi_u8 g_ahu20_temperature_buff[6]; 
extern hi_u8 g_ahu20_humidity_buff[6];
extern hi_u8 g_ahu20_gas_buff[6];

/*report traffic light count*/
extern hi_u32 g_red_led_auto_modu_time_count;
extern hi_u32 g_yellow_led_auto_modu_time_count;
extern hi_u32 g_green_led_auto_modu_time_count;
extern hi_u32 g_red_led_human_modu_time_count;
extern hi_u32 g_yellow_led_human_modu_time_count;
extern hi_u32 g_green_led_human_modu_time_count;
hi_u8 oc_beep_status = BEEP_OFF;
/*attribute initiative to report */
#define TAKE_THE_INITIATIVE_TO_REPORT
/*oc request id*/
#define CN_COMMADN_INDEX                    "commands/request_id="
/*oc report HiSpark attribute*/
#define COLORFUL_LIGHT_SERVICE_ID_PAYLOAD   "ColorfulLight"
#define COLORFUL_LIGHT_CONTROL_MODE_CMD     "ControlModule"
#define COLORFUL_LIGHT_COLORFUL_MODE_CMD    "ColorfulLightModule" 
#define COLORFUL_LIGHT_PWM_CONTROL_CMD      "PWM_Module"
#define COLORFUL_LIGHT_BRIGHTNESS_CMD       "BrightnessModule"
#define COLORFUL_LIGHT_HUMANDETECT_CMD      "HumanDetectModule"
#define COLORFUL_LIGHT_LIGHTDETECT_CMD      "LightDetectModule"     
#define COLORFUL_LIGHT_UNIONDETECT_CMD      "UnionDetectModule"
#define COLORFUL_LIGHT_BLUE_ON_PAYLOAD      "BLUE_LED_ON"
#define COLORFUL_LIGHT_RED_ON_PAYLOAD       "RED_LED_ON"
#define COLORFUL_LIGHT_GREEN_ON_PAYLOAD     "GREEN_LED_ON"
#define COLORFUL_LIGHT_PERIOD_1_S           "PERIOD_1_S"  
#define COLORFUL_LIGHT_PERIOD_05_S          "PERIOD_05_S"
#define COLORFUL_LIGHT_PERIOD_025_S         "PERIOD_025_S"  
#define COLORFUL_LIGHT_PWM_RED_LED_ON       "PWM_RED_LED_ON"
#define COLORFUL_LIGHT_PWM_GREEN_LED_ON     "PWM_GREEN_LED_ON"
#define COLORFUL_LIGHT_PWM_BLUE_LED_ON      "PWM_BLUE_LED_ON"
#define COLORFUL_LIGHT_PWM_PURPLE_LED_ON    "PWM_PURPLE_LED_ON"
#define COLORFUL_LIGHT_PWM_TRICOLOR_LED_ON  "PWM_TRICOLOR_LED_ON"
#define COLORFUL_LIGHT_BRIGHTNESS_LOW       "BRIGHTNESS_LOW_LED_ON"
#define COLORFUL_LIGHT_BRIGHTNESS_MIDDLE    "BRIGHTNESS_MIDDLE_LED_ON"
#define COLORFUL_LIGHT_BRIGHTNESS_HIGH      "BRIGHTNESS_HIGH_LED_ON"

#define TRAFFIC_LIGHT_CMD_PAYLOAD           "led_value"
#define TRAFFIC_LIGHT_CMD_CONTROL_MODE      "ControlModule"
#define TRAFFIC_LIGHT_CMD_AUTO_MODE         "AutoModule"
#define TRAFFIC_LIGHT_CMD_HUMAN_MODE        "HumanModule"
#define TRAFFIC_LIGHT_YELLOW_ON_PAYLOAD     "YELLOW_LED_ON"
#define TRAFFIC_LIGHT_RED_ON_PAYLOAD        "RED_LED_ON"
#define TRAFFIC_LIGHT_GREEN_ON_PAYLOAD      "GREEN_LED_ON"
#define TRAFFIC_LIGHT_SERVICE_ID_PAYLOAD    "TrafficLight"
#define TRAFFIC_LIGHT_BEEP_CONTROL          "BeepControl"
#define TRAFFIC_LIGHT_BEEP_ON               "BEEP_ON" 
#define TRAFFIC_LIGHT_BEEP_OFF              "BEEP_OFF"  
#define TRAFFIC_LIGHT_HUMAN_INTERVENTION_ON     "HUMAN_MODULE_ON"
#define TRAFFIC_LIGHT_HUMAN_INTERVENTION_OFF    "HUMAN_MODULE_OFF"    

#define ENVIRONMENT_SERVICE_ID_PAYLOAD      "Environment"
#define ENVIRONMENT_TEM_HUM_GAS_MODE        "AllEnvironmentValueCMD"
#define ENVIRONMENT_TEMPERATURE_PAYLOAD     "TemperatureModuleCMD"
#define ENVIRONMENT_HUMIDITY_PAYLOAD        "HumidityModuleCMD"
#define ENVIRONMENT_COMBUSTIBLE_GAS_PAYLOAD "CombustibleGasModuleCMD"


hi_void oc_colorful_light_app_option( hi_colorful_light_mode app_option_mode, hi_control_mode_type app_option_type)
{     
    g_current_mode = app_option_mode;
    switch (g_current_mode) {
        case CONTROL_MODE:
            // setup_clean_trfl_status(TRAFFIC_CONTROL_MODE);
            oc_colorful_light_status_report(CONTROL_MODE, setup_clfl_control_module);
            break;
        case COLORFUL_LIGHT_MODE:
            // setup_clean_trfl_status(TRAFFIC_AUTO_MODE);
            oc_colorful_light_status_report(COLORFUL_LIGHT_MODE, setup_clfl_colorful_light_module);
            break;
        case PWM_CONTROL_MODE:
            // setup_clean_trfl_status(TRAFFIC_HUMAN_MODE);
            oc_colorful_light_status_report(PWM_CONTROL_MODE, setup_clfl_pwm_control_module);
            break;
        case BIRGHTNESS_MODE:
            oc_colorful_light_status_report(BIRGHTNESS_MODE, setup_clfl_brightness_module);
            break;
        case HUMAN_DETECT_MODE:
            oc_colorful_light_status_report(HUMAN_DETECT_MODE, setup_clfl_human_detect_module);
            break;
        case LIGHT_DETECT_MODE:
            oc_colorful_light_status_report(LIGHT_DETECT_MODE, setup_clfl_light_detect_module);
            break; 
        case UNION_DETECT_MODE:
            oc_colorful_light_status_report(UNION_DETECT_MODE, setup_clfl_union_detect_module);
            break;               
        default:
            break;
    }  
}

hi_void oc_traffic_light_app_option( hi_traffic_light_mode app_option_mode, hi_control_mode_type app_option_type)
{     
    g_current_mode = app_option_mode;
    switch (g_current_mode) {
        case TRAFFIC_CONTROL_MODE:
            // setup_clean_trfl_status(TRAFFIC_CONTROL_MODE);
            oc_traffic_light_status_report(TRAFFIC_CONTROL_MODE, setup_trfl_control_module);
            break;
        case TRAFFIC_AUTO_MODE:
            // setup_clean_trfl_status(TRAFFIC_AUTO_MODE);
            oc_traffic_light_status_report(TRAFFIC_AUTO_MODE, setup_trfl_auto_module);
            break;
        case TRAFFIC_HUMAN_MODE:
            // setup_clean_trfl_status(TRAFFIC_HUMAN_MODE);
            oc_traffic_light_status_report(TRAFFIC_HUMAN_MODE, setup_trfl_human_module);
            break;
        default:
            break;
    }  
}
hi_void oc_environment_app_option( hi_environment_mode app_option_mode, hi_control_mode_type app_option_type)
{     
    g_current_mode = app_option_mode;
    switch (g_current_mode) {
        case ENV_ALL_MODE:
            // setup_clean_trfl_status(TRAFFIC_CONTROL_MODE);
            oc_environment_status_report(ENV_ALL_MODE, setup_env_all_module);
            break;
        case ENV_TEMPERRATURE_MODE:
            // setup_clean_trfl_status(TRAFFIC_AUTO_MODE);
            oc_environment_status_report(ENV_TEMPERRATURE_MODE, setup_env_temperature_module);
            break;
        case ENV_HUMIDITY_MODE:
            // setup_clean_trfl_status(TRAFFIC_HUMAN_MODE);
            oc_environment_status_report(ENV_HUMIDITY_MODE, setup_env_humidity_module);
            break;
        case COMBUSTIBLE_GAS_MODE:
            oc_environment_status_report(ENV_HUMIDITY_MODE, setup_env_combustible_gas_module);
            break;    
        default:
            break;
    }  
}
///< this is the callback function, set to the mqtt, and if any messages come, it will be called
///< The payload here is the json string
static void DemoMsgRcvCallBack(int qos, const char *topic, const char *payload)
{
    const char *requesID;
    char *tmp;
    IoTCmdResp_t resp;
    IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n",qos,topic, payload);
    tmp = strstr(topic,CN_COMMADN_INDEX);
    if(tmp != NULL){
        ///< now you could deal your own works here --THE COMMAND FROM THE PLATFORM

            ///< now er roport the command execute result to the platform
            requesID = tmp + strlen(CN_COMMADN_INDEX);
            resp.requestID = requesID;
            resp.respName = NULL;
            resp.retCode = 0;   ////< which means 0 success and others failed
            resp.paras = NULL;
            // IOT_LOG_DEBUG("respose paras------------------------------ = %s\r\n", resp.paras);
            (void)IoTProfileCmdResp(CONFIG_DEVICE_PWD,&resp);
    }
    return;
}


hi_void pets_send(char* keys, char* values)
{
    IoTProfileService_t service;
    IoTProfileKV_t property;

    memset(&property, 0, sizeof(property));
    property.type = EN_IOT_DATATYPE_STRING;
    property.key = keys;
    property.value = values;
    memset(&service, 0,sizeof(service));
    service.serviceID = "wdyxnnwpy";
    service.serviceProperty = &property;
    IoTProfilePropertyReport(CONFIG_DEVICE_ID,&service);

    hi_udelay(200000);

}


/*-------------------------------------------------------------------*/

#include <hi_gpio.h>
#include <hi_io.h>
#include <hi_uart.h>
#include <hi_pwm.h>
#include <hi_time.h>
#include <hi_types_base.h>
#include <hi_early_debug.h>
#include <hi_isr.h>
#include <hi_task.h>
#include <hi3861.h>
#include <stdio.h>

//#include "uart.h"
//#include "uart_drv.h"

#if 1

#define delay()     hi_udelay(2)
#define scl0()      hi_gpio_set_ouput_val(HI_GPIO_IDX_11,HI_GPIO_VALUE0)
#define scl1()      hi_gpio_set_ouput_val(HI_GPIO_IDX_11,HI_GPIO_VALUE1)
#define read(v)     hi_gpio_get_input_val(HI_IO_NAME_GPIO_12, &v)

#endif 

volatile hi_u8 uart1_tage=0;
volatile hi_char uart1_str[64];

void test(void){
    printf("123");
}


void uart1_config(void){

    hi_watchdog_disable();

    hi_io_set_func  (HI_IO_NAME_GPIO_0,HI_IO_FUNC_GPIO_0_UART1_TXD);
    hi_io_set_func  (HI_IO_NAME_GPIO_1,HI_IO_FUNC_GPIO_1_UART1_RXD);

    hi_uart_attribute uart_attr = {
        .baud_rate = 115200, /* baud_rate: 115200 */
        .data_bits = 8,      /* data_bits: 8bits */
        .stop_bits = 1,
        .parity = 0,
    };

    /* Initialize uart driver */
    hi_uart_init(HI_UART_IDX_1, &uart_attr, HI_NULL);

    return;
    

}
void uart1_handler(void* data){

    printf("enter");

}
void Rx_isr_config(void){

    hi_u32 rx_status = hi_reg_read_val32( 0x40009000 + 0x38);
    hi_reg_write32( 0x40009000 + 0x38, (unsigned short) (0x10 | rx_status));

    hi_irq_enable(39);
    hi_irq_request(39, HI_IRQ_FLAG_PRI3, (irq_routine)uart1_handler, 0);

}

void uart1_test(void){

    //Rx_isr_config();
    uart1_config();
    
    const hi_u8 uart_buff_ptr[10]="wdy zs!\n";
    #if 1
    for(;;){
    //hi_uart_write(HI_UART_IDX_1, uart_buff_ptr, 10);
     oled_show_str(10,5,uart1_str,1);
    if(uart1_tage){
   
    hi_udelay(1000000);
    uart1_tage=0;
    }
    }
    #endif
    return;
}


void pwm_config(void){

    hi_watchdog_disable();
    hi_io_set_func  (HI_IO_NAME_GPIO_9,HI_IO_FUNC_GPIO_9_GPIO);
    hi_gpio_set_dir (HI_GPIO_IDX_9,HI_GPIO_DIR_OUT);

    hi_io_set_func  (HI_IO_NAME_GPIO_10,HI_IO_FUNC_GPIO_10_GPIO);
    hi_gpio_set_dir (HI_GPIO_IDX_10,HI_GPIO_DIR_OUT);

    

}

void buzz_config(void){

    hi_gpio_set_ouput_val(HI_GPIO_IDX_6,HI_GPIO_VALUE0);

    hi_io_set_func  (HI_IO_NAME_GPIO_6,HI_IO_FUNC_GPIO_6_GPIO);
    hi_gpio_set_dir (HI_GPIO_IDX_6,HI_GPIO_DIR_OUT);

}

void buzz_on (void){hi_gpio_set_ouput_val(HI_GPIO_IDX_6,HI_GPIO_VALUE1);}
void buzz_off(void){hi_gpio_set_ouput_val(HI_GPIO_IDX_6,HI_GPIO_VALUE0);}

void cat_warn(void){    
       
    for(int tran=0;tran<4;++tran)
        {buzz_on();hi_udelay(250000);buzz_off();hi_udelay(250000);}

}
void dog_warn(void){
    
    for(int tran=0;tran<2;++tran)
        {buzz_on();hi_udelay(500000);buzz_off();hi_udelay(500000);}

}

void hx711_config(void){

    hi_watchdog_disable();
    hi_io_set_func  (HI_IO_NAME_GPIO_11,HI_IO_FUNC_GPIO_11_GPIO);
    hi_gpio_set_dir (HI_GPIO_IDX_11,HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_GPIO_IDX_11,HI_GPIO_VALUE0);

    hi_io_set_func  (HI_IO_NAME_GPIO_12,HI_IO_FUNC_GPIO_12_GPIO);
    hi_gpio_set_dir (HI_GPIO_IDX_12,HI_GPIO_DIR_IN);
}

long read_hx711(void){

    long value=0;
    hi_gpio_value temp;

    delay();
    scl0();
    delay();
    read(temp);

    while(temp)
        read(temp);

    for(int i=0;i<24;++i){

        scl1();
        delay();
        value<<=1;
        scl0();
        delay();
        read(temp);
        if(temp)
            value++;
    }
    scl1();
    delay();
    scl0();
    delay();
    value^=0x800000;

    return value;

}

double get_weight(void){

    double tran=0;
    for(int i=0;i<10;++i)
        tran+=read_hx711();
    tran/=4300;
    return tran;
}

extern hi_void oled_show_str(hi_u8 x, hi_u8 y, hi_u8 *chr, hi_u8 char_size);
extern hi_u8  *flaot_to_string(hi_double d, hi_u8 *str );
volatile hi_u8 empty_string[14]="             ";
void hx711_test(void){

    double temp=0,base=0;
    hi_u8 buf[14];
    hx711_config();
    
    printf("finish\n");
    base=get_weight();

    printf("%.2f\n",base);

    for(;;){
        hi_udelay(1000000);
        temp=get_weight()-base;
        //if(temp<0.01)
         //   continue;
        printf("%.2f\n",temp);
        //flaot_to_string(temp, buf);
        strcpy(buf,empty_string);
        sprintf(buf,"%.2f g",temp);
        printf("%s\n",buf);
        oled_show_str(10,5,empty_string,1);
        oled_show_str(10,5,buf,1);

    }

}


void cat_on(void){

    for(int i=0;i<9;++i){

        hi_gpio_set_ouput_val(HI_GPIO_IDX_9,HI_GPIO_VALUE1);
        hi_udelay(1500);
        hi_gpio_set_ouput_val(HI_GPIO_IDX_9,HI_GPIO_VALUE0);
        hi_udelay(18500);

    }

}

void cat_off(void){
    
    for(int i=0;i<9;++i){

        hi_gpio_set_ouput_val(HI_GPIO_IDX_9,HI_GPIO_VALUE1);
        hi_udelay(2500);
        hi_gpio_set_ouput_val(HI_GPIO_IDX_9,HI_GPIO_VALUE0);
        hi_udelay(17500);

    }

}

void dog_on(void){

    for(int i=0;i<9;++i){

        hi_gpio_set_ouput_val(HI_GPIO_IDX_10,HI_GPIO_VALUE1);
        hi_udelay(2500);
        hi_gpio_set_ouput_val(HI_GPIO_IDX_10,HI_GPIO_VALUE0);
        hi_udelay(17500);

    }

}

void dog_off(void){
    
    for(int i=0;i<9;++i){

        hi_gpio_set_ouput_val(HI_GPIO_IDX_10,HI_GPIO_VALUE1);
        hi_udelay(1500);
        hi_gpio_set_ouput_val(HI_GPIO_IDX_10,HI_GPIO_VALUE0);
        hi_udelay(18500);

    }

}

void f4_config(void){

    hx711_config();
    pwm_config();
    uart1_config();
    buzz_config();

}
static double base=0,weight=0,preweight=0;
static int dog_cnt=0,cat_cnt=0;
static double dog_last_food=0,dog_now_food=0,dog_total_food=0;
static double cat_last_food=0,cat_now_food=0,cat_total_food=0;

static char empty[20]="                  ";

static char catcnt[20];
static char catlast[20];
static char catnow[20];
static char cattotal[20];

static char dogcnt[20];
static char doglast[20];
static char dognow[20];
static char dogtotal[20];

void updata_cat(void){

    strcpy(catcnt,empty);
    strcpy(catlast,empty);
    strcpy(catnow,empty);
    strcpy(cattotal,empty);

    sprintf(catcnt,"cat_cnt: %d",cat_cnt);
    sprintf(catlast,"%.2f g",cat_last_food);
    sprintf(catnow,"%.2f g",cat_now_food);
    sprintf(cattotal,"%.2f g",cat_total_food);

    pets_send("cat_cnt",catcnt);
    pets_send("cat_last_food",catlast);
    pets_send("cat_now_food",catnow);
    pets_send("cat_total_food",cattotal);

    return;

}

void updata_dog(void){

    strcpy(dogcnt,empty);
    strcpy(doglast,empty);
    strcpy(dognow,empty);
    strcpy(dogtotal,empty);

    sprintf(dogcnt,"dog_cnt: %d",dog_cnt);
    sprintf(doglast,"%.2f g",dog_last_food);
    sprintf(dognow,"%.2f g",dog_now_food);
    sprintf(dogtotal,"%.2f g",dog_total_food);

    pets_send("dog_cnt",dogcnt);
    pets_send("dog_last_food",doglast);
    pets_send("dog_now_food",dognow);
    pets_send("dog_total_food",dogtotal);

    return;
      
}

static int cat_time=30,dog_time=30;


void f4_run(void){


    f4_config();

    updata_cat();
    updata_dog();
    

    base=get_weight();

    printf("%.2lf\n",base);


    while(1){

        if(uart1_tage){
           

            if((uart1_str[0]=='d')&&(uart1_str[2]=='g')){
                
                if(dog_last_food<50){

                dog_on();
                hi_udelay(1000000);
                dog_off();
                hi_udelay(1000000);

                }

                else
                    hi_udelay(3000000);

                weight=get_weight()-base;
                
                dog_cnt++;
                dog_now_food=weight-cat_now_food;
                dog_total_food+=weight;
                dog_last_food=preweight-cat_now_food;

                preweight=weight;

                updata_dog();

                dog_time=30;
                

            }
            else  if((uart1_str[0]=='c')&&(uart1_str[2]=='t')){

                if(cat_now_food<50){
            
                cat_on();
                hi_udelay(1000000);
                cat_off();
                hi_udelay(1000000);
                }

                else 
                    hi_udelay(3000000);

                weight=get_weight()-base;
                
                cat_cnt++;
                cat_now_food=weight-dog_now_food;
                cat_total_food+=weight;
                cat_last_food=preweight-dog_now_food;

                preweight=weight;

                updata_cat();

                cat_time=30;
                
                
            }


            uart1_tage=0;

        }
        else{
            hi_udelay(1000000);
            cat_time--;dog_time--;
            if(cat_time==0){
                cat_time=30;
                cat_warn();
            }
            if(dog_time==0){
                dog_time=30;
                dog_warn();
            }
        }

    }


}
/*-------------------------------------------------------------------*/


///< this is the demo main task entry,here we will set the wifi/cjson/mqtt ready ,and 
///< wait if any work to do in the while
static hi_void *DemoEntry(hi_void *arg)
{
    // IoTProfileService_t service;
    // IoTProfileKV_t property;
    hi_watchdog_disable();
    
    extern hi_void WifiStaReadyWait(hi_void);
    WifiStaReadyWait();

    extern void cJsonInit(void);
    cJsonInit();

    f4_config();

    IoTMain();
    IoTSetMsgCallback(DemoMsgRcvCallBack);
/*主动上报*/
#ifdef TAKE_THE_INITIATIVE_TO_REPORT


    //extern volatile hi_u8 uart1_tage;
    //extern volatile hi_char uart1_str[64];

    f4_run();
#endif
    return NULL;
}

///< This is the demo entry, we create a task here, and all the works has been done in the demo_entry
#define CN_IOT_TASK_STACKSIZE  0x1000   
#define CN_IOT_TASK_PRIOR 28
#define CN_IOT_TASK_NAME "IOTDEMO"
int app_demo_iot(void)
{
    hi_u32 ret;
    hi_task_attr attr = {0};
    hi_u32 taskID;

    attr.stack_size = CN_IOT_TASK_STACKSIZE;
    attr.task_prio = 28;
    attr.task_name = CN_IOT_TASK_NAME;
    
    ret = hi_task_create(&taskID, &attr, DemoEntry, NULL);
    if (ret != HI_ERR_SUCCESS) {
       IOT_LOG_ERROR("IOT TASK CTREATE FAILED");
    }

    return 0;
}
